package com.xiang.ad.sender.index;

import com.alibaba.fastjson.JSON;
import com.xiang.ad.dump.table.AdCreativeTable;
import com.xiang.ad.dump.table.AdCreativeUnitTable;
import com.xiang.ad.dump.table.AdPlanTable;
import com.xiang.ad.dump.table.AdUnitDistrictTable;
import com.xiang.ad.dump.table.AdUnitItTable;
import com.xiang.ad.dump.table.AdUnitKeywordTable;
import com.xiang.ad.dump.table.AdUnitTable;
import com.xiang.ad.handler.AdLevelDataHandler;
import com.xiang.ad.index.DataLevel;
import com.xiang.ad.mysql.constant.Constant;
import com.xiang.ad.mysql.dto.MySqlRowData;
import com.xiang.ad.sender.ISender;
import com.xiang.ad.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by xiang.
 * Binlog增量数据的投递，结果就是维护（更新）了索引系统中的增量索引
 * 投递过程：
 * MysqlRowData--->xxxTable
 * 然后调用AdLevelDataHandler的handleLevelx 更新对应的层级索引
 */
@Slf4j
@Component("indexSender")  //
public class IndexSender implements ISender {

    //根据不同层级，进行投递
    @Override
    public void sender(MySqlRowData rowData) {

        //获取层级
        String level = rowData.getLevel();

        // 投递路由 根据level对应处理
        if (DataLevel.LEVEL2.getLevel().equals(level)) {
            Level2RowData(rowData);
        } else if (DataLevel.LEVEL3.getLevel().equals(level)) {
            Level3RowData(rowData);
        } else if (DataLevel.LEVEL4.getLevel().equals(level)) {
            Level4RowData(rowData);
        } else {
            //用于调试代码
            log.error("MysqlRowData ERROR: {}", JSON.toJSONString(rowData));
        }
    }

    //第二层级的投递
    private void Level2RowData(MySqlRowData rowData) {

        //匹配判断
        if (rowData.getTableName().equals(
                Constant.AD_PLAN_TABLE_INFO.TABLE_NAME)) {//如果是plantable
            List<AdPlanTable> planTables = new ArrayList<>();

            //遍历填充
            for (Map<String, String> fieldValueMap :
                    rowData.getFieldValueMap()) {

                AdPlanTable planTable = new AdPlanTable();

                //填充各个属性，after部分，就是增量的部分
                fieldValueMap.forEach((k, v) -> {
                    switch (k) {
                        case Constant.AD_PLAN_TABLE_INFO.COLUMN_ID:
                            planTable.setId(Long.valueOf(v));
                            break;
                        case Constant.AD_PLAN_TABLE_INFO.COLUMN_USER_ID:
                            planTable.setUserId(Long.valueOf(v));
                            break;
                        case Constant.AD_PLAN_TABLE_INFO.COLUMN_PLAN_STATUS:
                            planTable.setPlanStatus(Integer.valueOf(v));
                            break;
                        case Constant.AD_PLAN_TABLE_INFO.COLUMN_START_DATE:
                            planTable.setStartDate(
                                    CommonUtils.parseStringDate(v)
                            );
                            break;
                        case Constant.AD_PLAN_TABLE_INFO.COLUMN_END_DATE:
                            planTable.setEndDate(
                                    CommonUtils.parseStringDate(v)
                            );
                            break;
                    }
                });

                //添加当前填充好的planTable，因为有很多个
                planTables.add(planTable);
            }

            //遍历planTables
            planTables.forEach(p ->
                    //调用AdLevelDataHandler实现增量索引的更新
                    AdLevelDataHandler.handleLevel2(p, rowData.getOpType()));
        } else if (rowData.getTableName().equals(
                //第二层级 还有 creative
                Constant.AD_CREATIVE_TABLE_INFO.TABLE_NAME
        )) {
            List<AdCreativeTable> creativeTables = new ArrayList<>();

            //遍历
            for (Map<String, String> fieldValeMap :
                    rowData.getFieldValueMap()) {

                AdCreativeTable creativeTable = new AdCreativeTable();

                //填充after部分字段，依次判断k对应的哪个列，然后对应填充对应的value
                fieldValeMap.forEach((k, v) -> {
                    switch (k) {
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_ID:
                            creativeTable.setAdId(Long.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_TYPE:
                            creativeTable.setType(Integer.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_MATERIAL_TYPE:
                            creativeTable.setMaterialType(Integer.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_HEIGHT:
                            creativeTable.setHeight(Integer.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_WIDTH:
                            creativeTable.setWidth(Integer.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_AUDIT_STATUS:
                            creativeTable.setAuditStatus(Integer.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_TABLE_INFO.COLUMN_URL:
                            creativeTable.setAdUrl(v);
                            break;
                    }
                });

                //
                creativeTables.add(creativeTable);
            }

            //实现增量索引的更新
            //使用AdLevelDataHandler
            //将数据对象xxxTable根据不同的操作类型去影响（构造、改变）到当前系统中的index
            creativeTables.forEach(c ->
            AdLevelDataHandler.handleLevel2(c, rowData.getOpType()));
        }
    }

    //第三层级的投递
    private void Level3RowData(MySqlRowData rowData) {

        //如果是adUnit这张表
        if (rowData.getTableName().equals(
                Constant.AD_UNIT_TABLE_INFO.TABLE_NAME)) {

            //存放结果  最终就是要转化为xxxTable
            List<AdUnitTable> unitTables = new ArrayList<>();

            for (Map<String, String> fieldValueMap :
                    rowData.getFieldValueMap()) {

                AdUnitTable unitTable = new AdUnitTable();

                //根据字段遍历转化/填充
                //依次判断k对应的哪个列，然后对应填充对应的value
                fieldValueMap.forEach((k, v) -> {
                    switch (k) {
                        case Constant.AD_UNIT_TABLE_INFO.COLUMN_ID:
                            unitTable.setUnitId(Long.valueOf(v));
                            break;
                        case Constant.AD_UNIT_TABLE_INFO.COLUMN_UNIT_STATUS:
                            unitTable.setUnitStatus(Integer.valueOf(v));
                            break;
                        case Constant.AD_UNIT_TABLE_INFO.COLUMN_POSITION_TYPE:
                            unitTable.setPositionType(Integer.valueOf(v));
                            break;
                        case Constant.AD_UNIT_TABLE_INFO.COLUMN_PLAN_ID:
                            unitTable.setPlanId(Long.valueOf(v));
                            break;
                    }
                });

                unitTables.add(unitTable);
            }

            unitTables.forEach(u ->
            AdLevelDataHandler.handleLevel3(u, rowData.getOpType()));
        } else if (rowData.getTableName().equals(
                Constant.AD_CREATIVE_UNIT_TABLE_INFO.TABLE_NAME
        )) {
            List<AdCreativeUnitTable> creativeUnitTables = new ArrayList<>();

            for (Map<String, String> fieldValueMap :
                    rowData.getFieldValueMap()) {

                AdCreativeUnitTable creativeUnitTable = new AdCreativeUnitTable();

                fieldValueMap.forEach((k, v) -> {
                    switch (k) {
                        case Constant.AD_CREATIVE_UNIT_TABLE_INFO.COLUMN_CREATIVE_ID:
                            creativeUnitTable.setAdId(Long.valueOf(v));
                            break;
                        case Constant.AD_CREATIVE_UNIT_TABLE_INFO.COLUMN_UNIT_ID:
                            creativeUnitTable.setUnitId(Long.valueOf(v));
                            break;
                    }
                });

                creativeUnitTables.add(creativeUnitTable);
            }


            //使用AdLevelDataHandler实现增量索引的更新
            //将数据对象xxxTable根据不同的操作类型去影响（构造、改变）到当前系统中的index
            creativeUnitTables.forEach(
                    u -> AdLevelDataHandler.handleLevel3(u, rowData.getOpType())
            );
        }
    }

    //第四层级的投递：关键词，兴趣，地域
    private void Level4RowData(MySqlRowData rowData) {

        //这里涉及的unit限制维度会比较多，用swtich比较好，以后扩展也方便，不用if
        switch (rowData.getTableName()) {

            case Constant.AD_UNIT_DISTRICT_TABLE_INFO.TABLE_NAME: //地域
                List<AdUnitDistrictTable> districtTables = new ArrayList<>();

                for (Map<String, String> fieldValueMap :
                        rowData.getFieldValueMap()) {

                    AdUnitDistrictTable districtTable = new AdUnitDistrictTable();

                    //after部分
                    //依次判断k对应的哪个列，然后对应填充对应的value
                    fieldValueMap.forEach((k, v) -> {
                        switch (k) {
                            case Constant.AD_UNIT_DISTRICT_TABLE_INFO.COLUMN_UNIT_ID:
                                districtTable.setUnitId(Long.valueOf(v));
                                break;
                            case Constant.AD_UNIT_DISTRICT_TABLE_INFO.COLUMN_PROVINCE:
                                districtTable.setProvince(v);
                                break;
                            case Constant.AD_UNIT_DISTRICT_TABLE_INFO.COLUMN_CITY:
                                districtTable.setCity(v);
                                break;
                        }
                    });

                    districtTables.add(districtTable);
                }

                //使用AdLevelDataHandler更新增量索引
                //将数据对象xxxTable根据不同的操作类型去影响（构造、改变）到当前系统中的index
                districtTables.forEach(
                        d -> AdLevelDataHandler.handleLevel4(d, rowData.getOpType())
                );
                break;
            case Constant.AD_UNIT_IT_TABLE_INFO.TABLE_NAME: //兴趣
                List<AdUnitItTable> itTables = new ArrayList<>();

                for (Map<String, String> fieldValueMap :
                        rowData.getFieldValueMap()) {

                    AdUnitItTable itTable = new AdUnitItTable();

                    fieldValueMap.forEach((k, v) -> {
                        switch (k) {
                            case Constant.AD_UNIT_IT_TABLE_INFO.COLUMN_UNIT_ID:
                                itTable.setUnitId(Long.valueOf(v));
                                break;
                            case Constant.AD_UNIT_IT_TABLE_INFO.COLUMN_IT_TAG:
                                itTable.setItTag(v);
                                break;
                        }
                    });
                    itTables.add(itTable);
                }
                itTables.forEach(
                        i -> AdLevelDataHandler.handleLevel4(i, rowData.getOpType())
                );
                break;
            case Constant.AD_UNIT_KEYWORD_TABLE_INFO.TABLE_NAME: //关键词

                List<AdUnitKeywordTable> keywordTables = new ArrayList<>();

                for (Map<String, String> fieldValueMap :
                        rowData.getFieldValueMap()) {
                    AdUnitKeywordTable keywordTable = new AdUnitKeywordTable();

                    fieldValueMap.forEach((k, v) -> {
                        switch (k) {
                            case Constant.AD_UNIT_KEYWORD_TABLE_INFO.COLUMN_UNIT_ID:
                                keywordTable.setUnitId(Long.valueOf(v));
                                break;
                            case Constant.AD_UNIT_KEYWORD_TABLE_INFO.COLUMN_KEYWORD:
                                keywordTable.setKeyword(v);
                                break;
                        }
                    });
                    keywordTables.add(keywordTable);
                }

                //使用AdLevelDataHandler实现增量索引的更新
                //将数据对象xxxTable根据不同的操作类型去影响（构造、改变）到当前系统中的index
                keywordTables.forEach(
                        k -> AdLevelDataHandler.handleLevel4(k, rowData.getOpType())
                );
                break;
        }
    }
}
